/*
Copyright 2016 Thomas Jammet
mathieu.poux[a]gmail.com
jammetthomas[a]gmail.com

This file is part of Librtmfp.

Librtmfp is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Librtmfp is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with Librtmfp.  If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "Base/Mona.h"
#include "Base/Event.h"
#include "AMF.h"
#include "AMFReader.h"
#include "Base/Packet.h"

struct FlashHandler : virtual Base::Object {
	typedef Base::Event<bool(const std::string& code, const std::string& description, Base::UInt16 streamId, Base::UInt64 flowId, double cbHandler)>	ON(Status); // NetConnection or NetStream status event
	typedef Base::Event<void(Base::UInt16 mediaId, Base::UInt32 time, const Base::Packet& packet, double lostRate, AMF::Type type)>						ON(Media);  // Received when we receive media (audio/video) in server or p2p 1-1

	FlashHandler(Base::UInt16 id, Base::UInt16 mediaId=0) : streamId(id), _mediaId(mediaId) {}
	virtual ~FlashHandler() {}

	const Base::UInt16	streamId;

	void			setIdMedia(Base::UInt16 idMedia) { _mediaId = idMedia; }

	bool			process(AMF::Type type, Base::UInt32 time, const Base::Packet& packet, Base::UInt64 flowId, Base::UInt64 writerId, double lostRate, bool lastFragment);

protected:

	Base::UInt16	_mediaId; // id generated by RTMFPSession to retrieve the player/publisher

	virtual bool	rawHandler(Base::UInt16 type, const Base::Packet& packet);
	virtual bool	dataHandler(const Base::Packet& packet, double lostRate);
	virtual bool	messageHandler(const std::string& name, AMFReader& message, Base::UInt64 flowId, Base::UInt64 writerId, double callbackHandler);
};

/**************************************************************
FlashStream is linked to an as3 NetStream
*/
struct FlashStream : FlashHandler, virtual Base::Object {
	typedef Base::Event<bool(const std::string& streamName, Base::UInt16 streamId, Base::UInt64 flowId, double cbHandler)>								ON(Play); // Received when a peer is trying to play a stream

	typedef Base::Event<void(const std::string& rawId, const std::string& peerId)>																		ON(NewPeer); // Received when the server send us a peer ID (after NetGroup connection)
	typedef Base::Event<bool(const std::string& groupId, const std::string& key, const std::string& peerId)>											ON(GroupHandshake); // Received when a connected peer send us the Group hansdhake (only for P2PSession)
	typedef Base::Event<bool(Base::BinaryReader& reader, Base::UInt16 streamId, Base::UInt64 flowId, Base::UInt64 writerId)>							ON(GroupMedia); // Received when a connected peer send us a peer Group Media (Subscription/Infos)
	typedef Base::Event<void(Base::BinaryReader& reader, Base::UInt16 streamId, Base::UInt64 flowId, Base::UInt64 writerId)>							ON(GroupReport);
	typedef Base::Event<void(Base::BinaryReader& reader, Base::UInt16 streamId, Base::UInt64 flowId, Base::UInt64 writerId)>							ON(GroupPlayPush);
	typedef Base::Event<void(Base::BinaryReader& reader, Base::UInt16 streamId, Base::UInt64 flowId, Base::UInt64 writerId, bool flush)>				ON(GroupPlayPull);
	typedef Base::Event<void(Base::BinaryReader& reader, Base::UInt16 streamId, Base::UInt64 flowId, Base::UInt64 writerId)>							ON(FragmentsMap);
	typedef Base::Event<void(Base::UInt16 streamId, Base::UInt64 flowId, Base::UInt64 writerId)>														ON(GroupBegin);
	typedef Base::Event<void(Base::UInt8 type, Base::UInt64 id, Base::UInt8 splitNumber, Base::UInt8 mediaType, Base::UInt32 time, 
		const Base::Packet& packet, double lostRate, Base::UInt16 streamId, Base::UInt64 flowId, Base::UInt64 writerId)>								ON(Fragment);
	typedef Base::Event<bool(Base::UInt16 streamId, Base::UInt64 flowId, Base::UInt64 writerId)>														ON(GroupAskClose); // Receiver when the peer want us to close the connection (if we accept we must close the current flow)
	typedef Base::Event<void(const std::string& message)>																								ON(GroupPost); // Group Post message received from a peer
	typedef Base::Event<void(Base::UInt8 type, std::string& reader)>																					ON(GroupPostKey); // Group Post key received from a peer

	FlashStream(Base::UInt16 id);
	virtual ~FlashStream();

	// return flase if writer is closed!
	virtual bool	process(const Base::Packet& packet, Base::UInt64 flowId, Base::UInt64 writerId, double lostRate, bool lastFragment);

private:
	virtual bool messageHandler(const std::string& name, AMFReader& message, Base::UInt64 flowId, Base::UInt64 writerId, double callbackHandler);
};
